/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package unilearn.dao.hibernate;

import java.lang.reflect.Method;
import java.util.List;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import unilearn.util.jdbc.HibernateUtil;

/**
 *
 * @author Yat
 */
public abstract class HibernateDAO {

    protected SessionFactory sessionFactory;

    public HibernateDAO() {
        sessionFactory = HibernateUtil.getSessionFactory();
    }

    public HibernateDAO(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    protected List getAll(String className) throws Exception {
        Session s = sessionFactory.openSession();
        Transaction t = s.beginTransaction();

        try {
            Query query = s.createQuery("from " + className);
            List objs = query.list();
            return objs;
        } finally {
            t.commit();
            s.close();
        }
    }

    protected Object find(Object obj) throws Exception {
        Session s = sessionFactory.openSession();
        Transaction t = s.beginTransaction();

        try {
            String queryString = getQueryString(obj);
            if (queryString == null) {
                return null;
            }

//            System.out.println("[HibernateDAO]getQueryString: " + queryString);//***
            Query query = s.createQuery(queryString);
            List objs = query.list();

//            if ((objs == null) || (objs.isEmpty())) {
//                return null;
//            }

            return objs;
        } finally {
            t.commit();
            s.close();
        }
    }

    protected String getQueryString(Object obj) throws Exception {
        String queryString = "from " + obj.getClass().getName() + " m";
        String whereString = "";

        Class model = Class.forName(obj.getClass().getName());

        for (Method m : model.getMethods()) {
            if ((!m.getName().equals("getClass")) && (m.getName().startsWith("get"))) {
                String mName = m.getName();
//                System.out.println("mathod: " + m.getName());//***
                mName = mName.substring(3, 4).toLowerCase() + mName.substring(4);

                try {
                    String value = m.invoke(obj, null).toString();
                    if (value.equals("-1")) {
                        throw new Exception();
                    }
                    whereString += "m." + mName + "='" + value + "' and ";
//                    System.out.println("[getQueryString]whereString: " + whereString);//***
                } catch (Exception e) {
                }
//                System.out.println("[getQueryString]method: " + m.getName() + " ,field: " + mName + ", value: " + (value == null ? "[null]" : value));//***
//                if (value != null) {
//                    whereString += "m." + mName + "='" + value + "' and ";
//                    System.out.println("[getQueryString]whereString: " + whereString);//***
//                }
            }
        }
//        System.out.println("foreach finished");//***
        whereString = whereString.substring(0, whereString.lastIndexOf(" and "));
//        System.out.println("[getQueryString]whereString(remove and): " + whereString);//***
        queryString += " where " + whereString;

        return queryString;
    }

    protected void insert(Object obj) throws Exception {
        Session s = sessionFactory.openSession();
//        Transaction t = s.beginTransaction();

        try {
            System.out.println(obj.toString());
            s.save(obj);
            s.flush();
            s.evict(obj);
        } finally {
//            t.commit();
            s.close();
        }
    }

    protected void update(Object obj) throws Exception {
        Session s = sessionFactory.openSession();
        Transaction t = s.beginTransaction();

        try {
            s.update(obj);
            s.flush();
            s.evict(obj);
        } finally {
            t.commit();
            s.close();
        }
    }

    protected void delete(Object obj) throws Exception {
        Session s = sessionFactory.openSession();
        Transaction t = s.beginTransaction();

        try {
            s.delete(obj);
            s.flush();
            s.evict(obj);
        } finally {
            t.commit();
            s.close();
        }
    }
}
